package com.example.comsys.service.impl;

import com.example.comsys.dao.AttendDAO;
import com.example.comsys.dataobject.AttendDO;
import com.example.comsys.model.Attend;
import com.example.comsys.model.Employee;
import com.example.comsys.model.EmployeeBase;
import com.example.comsys.model.Page;
import com.example.comsys.model.Result;
import com.example.comsys.param.AttendQueryParam;
import com.example.comsys.param.EmployeeQueryParam;
import com.example.comsys.param.PageQueryParam;
import com.example.comsys.service.AttendService;
import com.example.comsys.service.DepartmentService;
import com.example.comsys.service.EmployeeService;
import com.example.comsys.util.ConvertUtils;
import com.example.comsys.util.ConvertUtils.AttendUtils;
import com.example.comsys.util.ResultUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

/**
 * attend service impl
 *
 * @author wjh
 * @date 2020/1/2, 周四
 */
@Service
public class AttendServiceImpl implements AttendService {

  @Autowired
  private AttendDAO attendDAO;

  @Autowired
  private EmployeeService employeeService;

  @Autowired
  private DepartmentService departmentService;

  @Override
  public List<Attend> queryAttendsByParam(AttendQueryParam param) {
    if (param == null) {
      param = new AttendQueryParam();
    }
    param.setLimit(false);
    List<AttendDO> attendDos = attendDAO.selectByParam(param);
    if (CollectionUtils.isEmpty(attendDos)) {
      return new ArrayList<>();
    }
    return attendDos.stream()
        .map(AttendUtils::attendToModel)
        .filter(Objects::nonNull)
        .collect(Collectors.toList());
  }

  @Override
  public boolean deleteAttend(long id) {
    if (id <= 0) {
      return false;
    }
    return (attendDAO.deleteByPrimaryKey(id) == 1);
  }

  @Override
  public Result<String> addAttendRecord(Attend attend) {

    if (attend == null || attend.getEmployeeId() <= 0) {
      return null;
    }

    Employee employee = employeeService.queryEmployeeByEmployeeId(attend.getEmployeeId());
    if (employee == null) {
      return ResultUtils.newFailedResult("不存在该员工，非法操作");
    }
    attend.setName(employee.getName());

    LocalDate date = attend.getDate();
    AttendQueryParam queryParam = new AttendQueryParam();
    queryParam.setSpDate(ConvertUtils.localDateToDate(date));
    queryParam.setLimit(false);
    queryParam.setEmployeeId(attend.getEmployeeId());
    List<AttendDO> attendDos = attendDAO.selectByParam(queryParam);
    if (attendDos != null && attendDos.size() > 0) {
      return ResultUtils.newFailedResult("存在该员工当前日期的考勤记录，请删除后重新添加");
    }

    AttendDO attendDO = AttendUtils.attendToDO(attend);
    if (attendDO == null) {
      return ResultUtils.newFailedResult("模型转换失败，添加错误");
    }
    int insert = attendDAO.insert(attendDO);
    if (insert == 1) {
      attend.setId(attendDO.getId());
      return ResultUtils.newSuccessfulResult();

    }
    return ResultUtils.newFailedResult("未知错误");

  }

  @Override
  public Result<String> batchGenerateAttendRecord(long departId, LocalDateTime startDateTime, int endDay) {

    Result<String> result = new Result<>();
    result.setSuccess(false);

    startDateTime = LocalDateTime
        .of(startDateTime.getYear(), startDateTime.getMonth(), startDateTime.getDayOfMonth(), 0, 0, 0);
    LocalDateTime endDateTime = LocalDateTime
        .of(startDateTime.getYear(), startDateTime.getMonth(), endDay, 23, 59, 59);

    // 删除的记录
    int i = attendDAO.deleteByParam(departId, ConvertUtils.localDateTimeToDate(startDateTime),
        ConvertUtils.localDateTimeToDate(endDateTime));

    List<Employee> employees = employeeService.queryEmployeeByDepartment(departId);
    if (employees == null || employees.size() <= 0) {
      result.setMessage("该部门不存在员工，删除了【" + i + "】条记录");
      return result;
    }
    List<AttendDO> attendDos = new LinkedList<>();
    for (int dayOfMonth = startDateTime.getDayOfMonth(); dayOfMonth <= endDay; dayOfMonth++) {
      LocalTime now = LocalTime.now();
      LocalDate date = LocalDate.of(startDateTime.getYear(), startDateTime.getMonth(), dayOfMonth);
      LocalDateTime ldt = LocalDateTime.of(date, now);
      Date sqlDate = ConvertUtils.localDateTimeToDate(ldt);
      Random r = new Random();

      List<AttendDO> temp = employees.stream().map(v -> {
        int i1 = r.nextInt(11);
        AttendDO attend = new AttendDO();
        attend.setEmployeeId(v.getEmployeeId());
        attend.setName(v.getName());
        attend.setIllAbsence(false);
        attend.setThingAbsence(false);
        attend.setPubHoliday(false);
        attend.setLate(0);
        attend.setLeaveEarly(0);
        attend.setDate(sqlDate);
        if (i1 == 0) {
          attend.setPubHoliday(true);
        }
        if (i1 == 1 || i1 == 2) {
          attend.setLate(r.nextInt(100));
        }
        if (i1 % 3 == 0) {
          attend.setLeaveEarly(r.nextInt(100));
        }
        if (i1 ==7) {
          attend.setThingAbsence(true);
        }
        if (i1 == 10) {
          attend.setIllAbsence(true);
        }
        return attend;
      }).collect(Collectors.toList());
      attendDos.addAll(temp);
    }
    if (attendDos.size() == 0) {
      result.setMessage("没有需要创建的记录");
    } else {
      int insert = attendDAO.batchInsert(attendDos);
      result.setSuccess(true);
      result.setMessage(String.valueOf(i));
      result.setCode(String.valueOf(insert));
    }
    return result;
  }

  @Override
  public Page<Attend> queryDataByParam(AttendQueryParam queryParam) {

    if (queryParam == null) {
      return null;
    }
    PageQueryParam pageQueryParam = queryParam.getPageQueryParam();
    if (pageQueryParam == null) {
      pageQueryParam = new PageQueryParam();
      queryParam.setPageQueryParam(pageQueryParam);
    }
    List<AttendDO> attendDos = attendDAO.selectByParam(queryParam);
    if (attendDos == null || attendDos.size() == 0) {
      return new Page<>();
    }
    Integer count = attendDAO.selectCount();
    Set<Long> employeeIds = new HashSet<>();
    List<Attend> attends = attendDos.stream()
        .map(AttendUtils::attendToModel)
        .filter(Objects::nonNull)
        .peek(e -> employeeIds.add(e.getEmployeeId()))
        .collect(Collectors.toList());

    // 查询员工的部门信息
    EmployeeQueryParam employeeQueryParam = new EmployeeQueryParam();
    employeeQueryParam.setEmployeeIds(new ArrayList<>(employeeIds));
    employeeQueryParam.setDetailDepart(true);
    employeeQueryParam.setLimit(false);
    List<Employee> employees = employeeService.queryDataByParam(employeeQueryParam).getData();

    if (employees != null && employees.size() > 0) {
      Map<Long, Employee> map = employees.stream().collect(Collectors.toMap(EmployeeBase::getEmployeeId, e -> e));
      // 设置部门
      attends.forEach(v -> v.setDepartment(map.get(v.getEmployeeId()).getDepartment()));
    }
    // 排个序, 最新的记录放在上面
    attends.sort((o1, o2) -> {
      int i = o2.getDate().getYear() - o1.getDate().getYear();
      if (i != 0) {
        return i;
      }
      int i1 = o2.getDate().getMonthValue() - o1.getDate().getMonthValue();
      if (i1 != 0) {
        return i1;
      }
      int i2 = o2.getDate().getDayOfMonth() - o1.getDate().getDayOfMonth();
      if (i2 != 0) {
        return i2;
      }
      int i3 = (int) (o1.getDepartment().getDepartId() - o2.getDepartment().getDepartId());
      if (i3 != 0) {
        return i3;
      }
      return o1.getName().compareTo(o2.getName());
    });

    Page<Attend> data = new Page<>();
    data.setData(attends);
    data.setPageSize(queryParam.getPageQueryParam().getPageSize());
    data.setCurrentPage(queryParam.getPageQueryParam().getCurrentPage());
    data.setTotalItems(attends.size());
    data.setTotalPages(count / attends.size() + 1);
    data.setTotalSize(count);

    return data;
  }
}
